﻿var http        = require('http');
var url         = require('url');
var querystring = require('querystring');
var path        = require('path');
var fs          = require('fs');
var exec        = require('child_process').exec;
var format      = require('util').format;
var beautify    = require('js-beautify');
var uglifyjs    = require('uglify-js');
const BASE_DIR  = __dirname;
const PACK_CMD  = 'perl /path/to/jsPacker.pl -q -e62 -s -i %s -o %s';
const TMP_DIR   = 'tmp/';
const PORT      = 9000;
var MIMETYPES = {
  'css' : 'text/css',
  'htm' : 'text/html',
  'html': 'text/html',
  'js'  : 'application/javascript',
  'json': 'text/json',
  'ico' : 'image/x-icon',
  'jpg' : 'image/jpeg',
  'png' : 'image/png'
};

// 保存到本地临时文件
function saveFile(req, callback) {
    var file = TMP_DIR + Date.now() + '.js';
    var ws = fs.createWriteStream(file);
    ws.on('finish', function(){
        callback(file);
    });
    req.pipe(ws);
}
// 删除指定的本地文件
function removeFile(file) {
    fs.unlink(file, function(e){});
}
// 代码美化：JS
function beautify_js(data) {
    return beautify.js(data, {
        indent_size: 4,
        end_with_newline: true
    });
}
// 代码美化：CSS
function beautify_css(data) {
    return beautify.css(data, {
        indent_size: 2,
        newline_between_rules: true,
    });
}
// 代码美化：HTML
function beautify_html(data) {
    return beautify.html(data);
}
// Uglify压缩
function _uglify(file, res, callback) {
    try {
        // 压缩
        var result = uglifyjs.minify(file, {
            warnings: true,
            mangle: true,
            reserve: '$,require,exports'
        });
        callback(result);
    } catch (e) {
        res.write(e.message + '\nline: ' + e.line + '\ncol: ' + e.col);
        res.end();
    }
}
// 纯JS代码压缩
function uglify(req, res) {
    saveFile(req, function(file){
        _uglify(file, res, function(result) {
            //console.log('代码压缩完毕。');
            res.writeHead(200, {'Content-Type': "text/plain"});
            res.write(result.code);
            res.end();
        });
        removeFile(file);
    });
}
// jsPacker加密
function jspacker(req, res) {
    saveFile(req, function(file){
        var packFile = TMP_DIR + Date.now() + '.p.js';
        exec(format(PACK_CMD, file, packFile), function(err, output) {
            if (err) {
                res.write('出错了：' + err.message);
                res.end();
            } else {
                fs.createReadStream(packFile).pipe(res);
            }
            removeFile(file);
            setTimeout(function(){removeFile(packFile);}, 3000);
        });
    });
}
// 代码美化（格式化）
function beauty(req, res) {
    var location = url.parse(req.url);
    var opt = location.search && location.search.length > 1 ? querystring.parse(location.search.slice(1)) : {};
    saveFile(req, function(file){
        fs.readFile(file, 'utf8', function (err, data) {
            if (err) {
                //console.log(err);
                res.write('出错了：' + err.message);
                res.end();
                return;
            }
            removeFile(file);
            var result = opt.type === 'html' ? beautify_html(data) : opt.type === 'css' ? beautify_css(data) : beautify_js(data);
            console.log('代码美化完毕。');
            res.writeHead(200, {'Content-Type': "text/plain"});
            res.write(result);
            res.end();
        });
    });
}

function serveStatic(pathname, res) {
    pathname = path.normalize(pathname);
    var ext = path.extname(pathname).slice(1) || 'html';
    var file = BASE_DIR + '/' + pathname + (ext === 'html' ? '.html' : '');
    fs.stat(file, function(err, fstats) {
        if (err || !fstats.isFile()) {
            res.writeHead(404);
            res.write('Not Found');
            res.end();
        } else {
            res.writeHead(200, {'Content-Type': MIMETYPES[ext] || 'application/octec-stream'});
            fs.createReadStream(file).pipe(res);
        }
    });
}

http.createServer(function(req, res) {
    var location = url.parse(req.url);
    if (location.pathname === '/favicon.ico') {
        res.write('');
        res.end();
        return;
    }
    console.log(req.method, req.url);
    if (req.method === 'GET') {
        serveStatic(location.pathname, res);
    } else if (req.method === 'POST') { // 必须是POST请求
        switch (location.pathname) {
            case '/uglify'  : uglify(req, res);   break;
            case '/jspacker': jspacker(req, res); break;
            case '/beautify': beauty(req, res);   break;
            default         : res.write('无效的请求'); res.end(); break;
        }
    } else {
        res.write('无效的请求');
        res.end();
    }
}).listen(PORT);

console.log("server listening on port " + PORT);